﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace DeviceUnion.FFmpeg.WinForm
{
    public class FFRecorder : Recorder, IRecorder
    {
        public override void StartRecordDesktop(string file)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -framerate 6 -i desktop -vcodec libx264 \"{0}\"", file);
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordDesktop(string file, uint duration)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -t {0} -framerate 6 -i desktop -vcodec libx264 \"{1}\"", duration, file);
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordDesktop(string file, uint duration, string waterMarkStr)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -t {0} -framerate 6 -i desktop -vcodec libx264 ", duration);
            cmd += string.Format(" -vf drawtext=\"fontfile = msyh.ttc:x = 100:fontcolor = red:fontsize = 30:text='{0}'\"", waterMarkStr);
            cmd += " \"" + file+ "\"";
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordDesktop(string file, int x, int y, int w, int h)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -video_size {0}x{1} -offset_x {2} -offset_y {3} -framerate 6 -i desktop -vcodec libx264 ", w, h, x, y);
            cmd += " \"" + file + "\"";
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordWindow(string window, string file)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -i title=\"{0}\" -framerate 6 -vcodec libx264 -draw_mouse 0", window);
            cmd += " \"" + file + "\"";
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordWindow(string window, string file, uint duration)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -t {1} -i title=\"{0}\" -framerate 6 -vcodec libx264", duration, window);
            cmd += " \"" + file + "\"";
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordWindow(string window, string file, uint duration, string waterMarkStr)
        {
            var cmd = string.Format("ffmpeg -y -f gdigrab -r 10 -t {0} -i title=\"{1}\" -framerate 6 -vcodec libx264", duration, window);
            cmd += string.Format(" -vf drawtext=\"fontfile = msyh.ttc:x = w - tw:fontcolor = red:fontsize = 30:text='{0}'\"", waterMarkStr);
            cmd += " \"" + file + "\"";
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordDesktop(FFParam param)
        {
            var cmd = FParamAnalysister.Parse(param);
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public override void StartRecordWindow(FFParam param)
        {
            var cmd = FParamAnalysister.Parse(param);
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }

        public void ConvertTOGif(string mp4File, string gifFile, int duration)
        {
            var cmd = string.Format("ffmpeg -ss 0 -t {0} -i \"{1}\" -f gif \"{2}\"", duration, mp4File, gifFile);
            base.CmdProcess.StandardInput.WriteLine(cmd);
        }
    }

    public class FParamAnalysister
    {
        public static string Parse(FFParam param)
        {
            if (param.IsEmpty)
                return null;
            var cmd = new StringBuilder(" ffmpeg -y -f gdigrab ");
            if (!string.IsNullOrEmpty(param.LogLevel))
            {
                cmd.Append(string.Format("-v {0} ", param.LogLevel));
            }
            if (param.Duration > 0)
            {
                cmd.Append(string.Format("-t {0} ", param.Duration));
            }
            if (param.Rate > 0)
            {
                cmd.Append(string.Format("-r {0} ", param.Rate));
            }
            if (param.FrameRate > 0)
            {
                cmd.Append(string.Format("-framerate {0} ", param.FrameRate));
            }
            if (!param.VideoSize.IsEmpty)
            {
                cmd.Append(string.Format("-video_size {0}x{1} ", param.VideoSize.Width, param.VideoSize.Height));
            }
            if (!param.VideoOffSet.IsEmpty)
            {
                cmd.Append(string.Format("-offset_x {0} -offset_y {1} ", param.VideoOffSet.X, param.VideoOffSet.Y));
            }
            if (param.Window == null)
            {
                cmd.Append(string.Format(" -i desktop"));
            }
            else
            {
                cmd.Append(string.Format(" -i title=\"{0}\" ", param.Window));
            }
            cmd.Append(string.Format(" -vcodec {0} ", param.VideoCodec));
            if (param.WaterMarkText.IsEmpty)
            {
                cmd.Append(string.Format(" {0} ", param.WaterMarkText.ToString()));
            }
            if (param.Tags.Count > 0)
            {
                for (int i = 0; i < param.Tags.Count; i++)
                {
                    cmd.Append(string.Format(" {0} ", param.Tags[i]));
                }
            }
            if (param.Mute)
            {
                cmd.Append(" -an ");
            }
            cmd.Append(" \"" + param.OutFile+"\"");
            return cmd.ToString();
        }
    }

    public enum VCodec
    {
        /// <summary>
        /// H264编码
        /// </summary>
        libx264,
    }

    /// <summary>
    /// 水印文字
    /// </summary>
    public struct WaterMark
    {
        public static WaterMark Empty
        {
            get
            {
                return new WaterMark();
            }
        }
        public bool IsEmpty { get; set; }
        /// <summary>
        /// 字体文件
        /// </summary>
        public string FontFile { get; set; }
        /// <summary>
        /// X坐标
        /// </summary>
        public string XLocation { get; set; }
        /// <summary>
        /// Y坐标
        /// </summary>
        public string YLocation { get; set; }
        /// <summary>
        /// 字体颜色
        /// </summary>
        public string FontColor { get; set; }
        /// <summary>
        /// 字体大小
        /// </summary>
        public uint FontSize { get; set; }
        /// <summary>
        /// 文字内容
        /// </summary>
        public string Text { get; set; }
        /// <summary>
        /// 是否使用时间代替文字
        /// </summary>
        public bool UseTimeReplaceText { get; set; }
        /// <summary>
        /// 其他参数
        /// </summary>
        public string Tag { get; set; }
        public override string ToString()
        {
            if (!IsEmpty)
                return null;
            var txt = UseTimeReplaceText ? "%{localtime\\:%Y-%m-%d %H-%M-%S}" : Text;
            var str = string.Format("-vf drawtext=\"fontfile={0}:x={1}:y={2}:fontcolor={3}:fontsize={4}:text='{5}'", FontFile, XLocation, YLocation, FontColor, FontSize, txt);
            str += Tag+ "\"";
            return str;
        }
    }

    /// <summary>
    /// FFmpeg参数
    /// </summary>
    public struct FFParam
    {
        public static FFParam Empty
        {
            get
            {
                return new FFParam() { IsEmpty = true,WaterMarkText = WaterMark.Empty };
            }
        }

        public bool IsEmpty { get; set; }

        [Description("-i title={0}")]
        public string Window { get; set; }

        /// <summary>
        /// 输出文件
        /// </summary>
        [Description("{0}")]
        public string OutFile { get; set; }

        /// <summary>
        /// 视频编码格式
        /// </summary>
        [Description("-vcodec {0}")]
        public VCodec VideoCodec { get; set; }

        /// <summary>
        /// 帧率
        /// </summary>
        [Description("-r {0}")]
        public int Rate { get; set; }
        /// <summary>
        /// 
        /// </summary>
        [Description("-framerate {0}")]
        public int FrameRate { get; set; }

        /// <summary>
        /// 裁剪大小
        /// </summary>
        [Description("-video_size {0}x{1}")]
        public System.Drawing.Size VideoSize { get; set; }

        /// <summary>
        /// 位置
        /// </summary>
        [Description("-offset_x {0} -offset_y {1}")]
        public System.Drawing.Point VideoOffSet { get; set; }

        /// <summary>
        /// 录制时长S 时长结束后 自动结束
        /// </summary>
        [Description("-t {0}")]
        public int Duration { get; set; }

        /// <summary>
        /// 日志等级
        /// </summary>
        [Description("-v {0}")]
        public string LogLevel { get; set; }
        
        /// <summary>
        /// 是否静音
        /// </summary>
        [Description("-an")]
        public bool Mute { get; set; }

        /// <summary>
        /// 水印文字
        /// </summary>
        [Description(" -vf drawtext=\"fontfile = msyh.ttc:x = w - tw:fontcolor = red:fontsize = 30:text='{0}'\"")]
        public WaterMark WaterMarkText { get; set; }

        private List<string> _tags;
        /// <summary>
        /// 附加参数
        /// </summary>
        public List<string> Tags
        {
            get
            {
                if (_tags == null)
                    _tags = new List<string>(); 
                return _tags;
            }
        }
    }
}
